﻿#include "gametimer.h"
#include <algorithm>

GameTimer game_timer;

bool GameEvent::operator < (GameEvent &ge1)
{
	return time < ge1.time;
}

GameTimer::GameTimer()
{
}

GameTimer::~GameTimer()
{
	gameevents.clear();
	spell_patterns.clear();
}

void GameTimer::Load(CL_ResourceManager &resources, CL_String name)
{
	leveltime = 0;
	currentevent = 0;
	paused = false;
	gameevents.clear();

	CL_DomElement element = resources.get_resource(name).get_element();
	std::vector<CL_DomNode> event_nodes = element.select_nodes("event");
	for (size_t i = 0; i < event_nodes.size(); i++)
	{
		CL_DomElement event_element = event_nodes[i].to_element();
		GameEvent new_event;
		new_event.time = CL_StringHelp::text_to_float(event_element.get_attribute("time"));
		if (event_element.get_attribute("name") == "enemy" || event_element.get_attribute("name") == "boss")
		{
			// запускается враг
			if (event_element.get_attribute("name") == "enemy")
				new_event.eventtype = 0; // обычный противник
			else
				new_event.eventtype = 1; // босс
			std::vector<CL_String> params = CL_StringHelp::split_text(event_element.get_child_string("params"), ";");
			// Позиция отсчитывается от левого края области вывода для удобства
			new_event.position_x = global_state.render_field.left + CL_StringHelp::text_to_float(params[0]);
			new_event.position_y = CL_StringHelp::text_to_float(params[1]);
			new_event.move = CL_StringHelp::text_to_float(params[2]);
			new_event.angle = CL_StringHelp::text_to_float(params[3]);
			// Скорость в скрипте увеличена на 1000 для удобства записи
			new_event.base_speed = CL_StringHelp::text_to_float(params[4]) / 1000.0f;
			new_event.speed = CL_StringHelp::text_to_float(params[5]) / 1000.0f;
			new_event.collision = CL_StringHelp::text_to_float(params[6]);
			new_event.version = CL_StringHelp::text_to_int(params[7]);
			new_event.hp = CL_StringHelp::text_to_int(params[8]);
			new_event.score = CL_StringHelp::text_to_int(params[9]);
			new_event.bonus = CL_StringHelp::text_to_int(params[10]);
			new_event.path = event_element.get_child_string("path");
			new_event.render = event_element.get_child_string("render");
			// Выстрелы
			CL_String shots = event_element.get_child_string("shots");
			if (shots != "")
			{
				if (event_element.get_attribute("name") == "enemy")
				{
					// Обычный противник
					// Обычные выстрелы
					std::vector<CL_String> sts = CL_StringHelp::split_text(CL_StringHelp::trim(shots), ",");
					new_event.shots = sts.size();
					for (int s = 0; s < new_event.shots; s++)
					{
						std::vector<CL_String> shotparams = CL_StringHelp::split_text(sts[s], ";");
						new_event.bullet_patterns[s].launch_type = CL_StringHelp::text_to_int(shotparams[0]);
						new_event.bullet_patterns[s].launch = CL_StringHelp::text_to_int(shotparams[1]);
						new_event.bullet_patterns[s].type = CL_StringHelp::text_to_int(shotparams[2]);
					}
				}
				else
				{
					// Босс
					// В данном случае в shots хранится количество спеллкарт
					new_event.shots = CL_StringHelp::text_to_int(event_element.get_child_string("shots"));
					// Имя босса
					CL_String boss_name = event_element.get_child_string("name");
					new_event.string_param = boss_name;
					// Диалог босса
					CL_String dialog_name = event_element.get_child_string("dialog");
					new_event.string_param_other = dialog_name;
					if (dialog_name == "")
						new_event.have_dialog = 0;
					else
						new_event.have_dialog = 1;
					// Спеллкарты босса
					for (int s = 0; s < new_event.shots; s++)
					{
						CL_String nname = CL_String("spellcard") + CL_StringHelp::int_to_text(s + 1);
						CL_DomElement spell_element = event_element.select_node(nname).to_element();
						_SpellPattern sp;
						sp.spell = spell_element.get_child_string("spell");
						sp.nonspell = spell_element.get_child_string("nonspell");
						sp.spellhp = CL_StringHelp::text_to_int(spell_element.get_child_string("hp_nonspell"));
						sp.nonspellhp = CL_StringHelp::text_to_int(spell_element.get_child_string("hp_spell"));
						sp.price = CL_StringHelp::text_to_int(spell_element.get_child_string("price"));
						std::vector<CL_String> spos = CL_StringHelp::split_text(spell_element.get_child_string("start_position"), ";");
						sp.start_position.x = global_state.render_field.left + CL_StringHelp::text_to_float(spos[0]);
						sp.start_position.y = CL_StringHelp::text_to_float(spos[1]);
						sp.start_speed = CL_StringHelp::text_to_float(spell_element.get_child_string("start_speed")) / 1000.0f; // Тоже увеличена на 1000
						sp.start_wait = CL_StringHelp::text_to_float(spell_element.get_child_string("start_wait"));
						spell_patterns[boss_name.c_str()].push_back(sp);
					}
				}
			}
			else
			{
				new_event.shots = 0;
			}
			if (event_element.get_child_string("f1") != "")
				new_event.float_param = CL_StringHelp::text_to_float(event_element.get_child_string("f1"));
			else
				new_event.float_param = 0;
		}
		else if (event_element.get_attribute("name") == "dialog")
		{
			// запустить диалог
			new_event.eventtype = 10;
			new_event.string_param = event_element.get_child_string("title");
		}
		else if (event_element.get_attribute("name") == "effect")
		{
			// запустить эффект
			new_event.eventtype = 20;
			new_event.string_param = event_element.get_child_string("effect");
		}
		else if (event_element.get_attribute("name") == "level_end")
		{
			// уровень оканчивается просто так
			new_event.eventtype = 100;
		}
		else if (event_element.get_attribute("name") == "wait")
		{
			// Остановка отсчёта игрового времени на указанное время
			new_event.eventtype = 500;
			new_event.float_param = CL_StringHelp::text_to_float(event_element.get_child_string("time"));
		}
		gameevents.push_back(new_event);
	}
	sort(gameevents.begin(), gameevents.end());
}

void GameTimer::Process(float time)
{
	if (currentevent >= gameevents.size())
		return;
	if (paused)
	{
		pause_time -= time;
		if (pause_time < 0)
			paused = false;
		else
			return;
	}
	leveltime += time;
	while((currentevent < gameevents.size()) && (leveltime > gameevents[currentevent].time))
	{
		// エヴェント発射!!
		if (gameevents[currentevent].eventtype == 0)
		{
			// Появление врага
			Enemy new_enemy;
			CL_Angle tmp_angle(gameevents[currentevent].move, cl_degrees);
			new_enemy.position.x = gameevents[currentevent].position_x;
			new_enemy.position.y = gameevents[currentevent].position_y;
			new_enemy.move = CL_Vec2<float>(cos(tmp_angle.to_radians()), sin(tmp_angle.to_radians()));
			new_enemy.orientation = CL_Angle(gameevents[currentevent].angle, cl_degrees);
			new_enemy.base_speed = gameevents[currentevent].base_speed;
			new_enemy.speed = gameevents[currentevent].speed;
			new_enemy.version = gameevents[currentevent].version;
			new_enemy.hp = gameevents[currentevent].hp;
			new_enemy.score = gameevents[currentevent].score;
			new_enemy.path = patterns.GetEnemyPath(gameevents[currentevent].path);
			new_enemy.appearance = renders.GetEnemyRender(gameevents[currentevent].render);
			new_enemy.collision_size = gameevents[currentevent].collision;
			new_enemy.shots = gameevents[currentevent].shots;
			new_enemy.bonus_drop = gameevents[currentevent].bonus;
			new_enemy.animation_frame = 0;
			new_enemy.time_from_last_frame = 0;
			new_enemy.time_lived = 0;
			new_enemy.dead = 0;
			new_enemy.is_boss = 0;
			new_enemy.param_float1 = gameevents[currentevent].float_param;
			new_enemy.trigger = 0;
			for (int i = 0; i < 64; i++)
				new_enemy.bullet_patterns[i] = gameevents[currentevent].bullet_patterns[i];
			new_enemy.Update(leveltime - gameevents[currentevent].time);
			emanager.Create(new_enemy);
			cl_log_event("Game Event", "Create Enemy at  %1 , %2", gameevents[currentevent].position_x, gameevents[currentevent].position_y);
		}
		else if (gameevents[currentevent].eventtype == 1)
		{
			// Запуск босса
			EnemyBoss new_enemy;
			CL_Angle tmp_angle(gameevents[currentevent].move, cl_degrees);
			new_enemy.position.x = gameevents[currentevent].position_x;
			new_enemy.position.y = gameevents[currentevent].position_y;
			new_enemy.move = CL_Vec2<float>(cos(tmp_angle.to_radians()), sin(tmp_angle.to_radians()));
			new_enemy.orientation = CL_Angle(gameevents[currentevent].angle, cl_degrees);
			new_enemy.base_speed = gameevents[currentevent].base_speed;
			new_enemy.speed = gameevents[currentevent].speed;
			new_enemy.version = gameevents[currentevent].version;
			new_enemy.hp = gameevents[currentevent].hp;
			new_enemy.score = gameevents[currentevent].score;
			new_enemy.path = patterns.GetEnemyPath(gameevents[currentevent].path);
			new_enemy.appearance = renders.GetEnemyRender(gameevents[currentevent].render);
			new_enemy.collision_size = gameevents[currentevent].collision;
			new_enemy.shots = gameevents[currentevent].shots;
			new_enemy.bonus_drop = gameevents[currentevent].bonus;
			new_enemy.animation_frame = 0;
			new_enemy.time_from_last_frame = 0;
			new_enemy.time_lived = 0;
			new_enemy.dead = 0;
			new_enemy.param_float1 = gameevents[currentevent].float_param;
			new_enemy.have_dialog = gameevents[currentevent].have_dialog;
			new_enemy.dialog_name = gameevents[currentevent].string_param_other;
			new_enemy.trigger = 0;
			// Параметры босса
			new_enemy.is_boss = 1;
			new_enemy.name = gameevents[currentevent].string_param;
			new_enemy.current_spellcard = 0;
			new_enemy.current_spellcard_action = 0;
			new_enemy.current_spell_level = 0;
			new_enemy.spell_patterns = spell_patterns[new_enemy.name.c_str()];
			new_enemy.rnd_rings = 0;
			new_enemy.Update(leveltime - gameevents[currentevent].time);
			emanager.Create(new_enemy);
			cl_log_event("Game Event", "Create Boss Enemy at  %1 , %2", gameevents[currentevent].position_x, gameevents[currentevent].position_y);
			// Переключить статус в режим битвы с боссом
			global_state.game_boss_battle = 1;
		}
		else if (gameevents[currentevent].eventtype == 10)
		{
			// Запуск диалога
			global_state.game_dialog = 1;
			// Определить какой язык запускать
			// 0 - русский, 1 - японский
			CL_String dialog_name = gameevents[currentevent].string_param;
			if (global_state.lang == 0)
				dialog_name += "_rus";
			if (global_state.lang == 1)
				dialog_name += "_jap";
			dialogs.StartDialog(dialog_name);
			cl_log_event("Game Event", "Start Dialog %1", dialog_name);
		}
		else if (gameevents[currentevent].eventtype == 500)
		{
			// Включение паузы
			paused = true;
			pause_time = gameevents[currentevent].float_param - (leveltime - gameevents[currentevent].time);
			leveltime = gameevents[currentevent].time;
		}
		else if (gameevents[currentevent].eventtype == 100)
		{
			// Конец уровня
			global_state.game_level_end = 1;
		}
		currentevent++;
	}
}
